'''
Created on 2011-12-02

@author: stuart
'''
from OpenGL.GL import *
import numpy

class Ground():
    def __init__(self, width, depth, pos):
        self.w = width
        self.d = depth
        self.pos = pos
        
        w2 = width / 2
        d2 = depth / 2
        posX = pos[0]
        posY = pos[1]
        posZ = pos[2]
        
        self.vertices = numpy.array([-w2 + posX, posY, -d2 + posZ, 1.,
                                     -w2 + posX, posY,  d2 + posZ, 1.,
                                      w2 + posX, posY,  d2 + posZ, 1.,
                                      w2 + posX, posY, -d2 + posZ, 1.], dtype='float32')
        self.edges = numpy.array([0, 1, 2, 3], dtype='uint32') 
        
        # set shader sources
        self.vshader_src = """
            #version 110
            
            uniform mat4 mvTransform;
            uniform mat4 pmvTransform;            
            
            varying vec3 N;
            varying vec3 v;
            void main(void)  
            {     
               v = vec3(mvTransform * gl_Vertex);       
               N = normalize(gl_Normal);
               gl_Position = pmvTransform * gl_Vertex;  
            }
            """
            
        self.fshader_src = """
            #version 110
           
            varying vec3 N;
            varying vec3 v;    
            uniform vec4 lightPos;
            uniform vec4 ambient;
            uniform vec4 diffuse;
            uniform vec4 specular;
            uniform float shininess;
            uniform vec4 color;
            
            void main (void)  
            {  
               vec3 L = normalize(lightPos.xyz - v);   
               vec3 E = normalize(-v); // we are in Eye Coordinates, so EyePos is (0,0,0)  
               vec3 R = normalize(-reflect(L,N));  
             
               //calculate Ambient Term:  
               vec4 Iamb = ambient;    
            
               //calculate Diffuse Term:  
               vec4 Idiff = diffuse * max(dot(N,L), 0.0);
               Idiff = clamp(Idiff, 0.0, 1.0);     
               
               // calculate Specular Term:
               vec4 Ispec = specular * pow(max(dot(R,E),0.0),0.3*shininess);
               Ispec = clamp(Ispec, 0.0, 1.0);               
               
               // write Total Color:  
               gl_FragColor = color * (Idiff + Iamb + Ispec); // vec4(N, 1.0);
            }
            """        

        self.color = [0.75, 0.75, 0.75, 1.0]
        self.glStatus = False
        
        
    def initializeGL(self):
        # compile and link shader
        vshader_id = glCreateShader(GL_VERTEX_SHADER)
        glShaderSource(vshader_id, self.vshader_src)
        glCompileShader(vshader_id)
        print("curtain vertex shader compile status: "+
                str(glGetShaderiv(vshader_id, GL_COMPILE_STATUS)))
        print(glGetShaderInfoLog(vshader_id))

        fshader_id = glCreateShader(GL_FRAGMENT_SHADER)
        glShaderSource(fshader_id, self.fshader_src)
        glCompileShader(fshader_id)
        print("curtain fragment shader compile status: "+
                str(glGetShaderiv(fshader_id, GL_COMPILE_STATUS)))
        print(glGetShaderInfoLog(fshader_id))

        self.shader = glCreateProgram()
        glAttachShader(self.shader, vshader_id)
        glAttachShader(self.shader, fshader_id)
        glLinkProgram(self.shader)

        self.mvLocation = glGetUniformLocation(self.shader, "mvTransform")
        self.pmvLocation = glGetUniformLocation(self.shader, "pmvTransform")
        self.nTransformLocation = glGetUniformLocation(self.shader, "normalTransform")
        self.colorLocation = glGetUniformLocation(self.shader, "color")
        
        self.lightPosLocation = glGetUniformLocation(self.shader, "lightPos")
        self.lightAmbientLocation = glGetUniformLocation(self.shader, "ambient")
        self.lightDiffuseLocation = glGetUniformLocation(self.shader, "diffuse")
        self.lightSpecularLocation = glGetUniformLocation(self.shader, "specular")
        self.lightShininessLocation = glGetUniformLocation(self.shader, "shininess")
        
         # then set up VBO stuff
        self.meshbuffers = glGenBuffers(2)
        glBindBuffer(GL_ARRAY_BUFFER, self.meshbuffers[0])
        glBufferData(GL_ARRAY_BUFFER, self.vertices, GL_STATIC_DRAW)
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.meshbuffers[1])
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, self.edges, GL_STATIC_DRAW)
        
        # remember that initialization is complete
        self.glStatus = True
        
    def initialized(self):
        return self.glStatus

    def update(self, dT):
        # do nothing
        return
    
    def reset(self):
        # do nothing
        return
   
    def paintGL(self, mvTransform, pmvTransform, light):
        glUseProgram(self.shader)
        glUniformMatrix4fv(self.mvLocation, 1, True, mvTransform.flatten())
        glUniformMatrix4fv(self.pmvLocation, 1, True, pmvTransform.flatten())
        glUniform4fv(self.colorLocation, 1, self.color)
        glUniform4fv(self.lightPosLocation, 1, light.getPos())
        glUniform4fv(self.lightAmbientLocation, 1, light.getAmbient())
        glUniform4fv(self.lightDiffuseLocation, 1, light.getDiffuse())
        glUniform4fv(self.lightSpecularLocation, 1, light.getSpecular())
        glUniform1f(self.lightShininessLocation, light.getShininess())
                
        glEnableClientState(GL_VERTEX_ARRAY)
        glBindBuffer(GL_ARRAY_BUFFER, self.meshbuffers[0])
        glBufferData(GL_ARRAY_BUFFER, self.vertices, GL_STATIC_DRAW)
        glVertexPointer(4, GL_FLOAT, 0, None)
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.meshbuffers[1])
        glDrawElements(GL_QUADS, len(self.edges), GL_UNSIGNED_INT, None)
        glDisableClientState(GL_VERTEX_ARRAY)
        
